/* Matías Blanco & Sergio Pérez      */
/* Negocio de Servicios Informáticos. Práctica 5 - Monitores en Java */

package negociojava;

import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

enum TipoEstadoEmpresa{Funcionamiento, Bancarrota};

public class Main {
    final static int MAXCLIENTES = 50;
    
    public static void main(String[] args) {
        Director director=new Director();
        
        // Creamos y lanzamos las tareas que representan a los
        Cliente cliente;
        System.out.println("---- COMIENZAN A SALIR PERSONAS");System.out.println();
        for(int i=0; i < MAXCLIENTES; i++){
            cliente = new Cliente(i+1,director);
            cliente.start();
        }
    }
}

class Director{
    // Costantes y variables
    final int PRECIOCONTRATAR = 5;
    final int MINCAPITAL = 10;
    
    int Trabajadores = 40; // Trabajadores iniciales
    int Dinero = 100; // Partimos de un dinero
    TipoEstadoEmpresa Estado = TipoEstadoEmpresa.Funcionamiento;
    Random rd = new Random();
    int contratados;

    public Director(){

    }

      
    public synchronized int SolicitarServicio() {
        int rand;
        int tbj=0;
        if (Estado != TipoEstadoEmpresa.Bancarrota) {
            // Generamos el numero de trabajadores que vamos a enviar
            rand = rd.nextInt(4) + 1;
            if (rand > Trabajadores) {
                rand = Trabajadores;
            }
            Trabajadores = Trabajadores - rand;
            tbj = rand;
        }
        return tbj;
    }

    public synchronized void Pagar(int pago){
        // Añadimos los empleados y el dinero
        Dinero = Dinero + pago;

        // Vemos si podemos contratar si es asi contratamos
        if (PRECIOCONTRATAR < (Dinero - MINCAPITAL)) {
            // Contratamos todos lo que podamos con el dinero que tenemos
            contratados = ((Dinero - MINCAPITAL) / PRECIOCONTRATAR);
            Trabajadores = Trabajadores + contratados;
            Dinero = Dinero - (contratados * PRECIOCONTRATAR);
            System.out.println("<!! La empresa ha contratado a "+contratados+" trabajadores.");
        }

        if (Estado == TipoEstadoEmpresa.Bancarrota && Trabajadores > 0) {
            System.out.println("//-!! La empresa ya no esta en Bancarrota !!//-");
            Estado = TipoEstadoEmpresa.Funcionamiento;
        }
    }

    public synchronized int Demandar() {
        // Generamos la compensación que le vamos a dar al cliente
        int compensacion = (rd.nextInt(4) + 1) * 3;
        if (compensacion > Dinero) {
            compensacion = Dinero;
            Estado = TipoEstadoEmpresa.Bancarrota;
            System.out.println("!! La empresa esta en Bancarrota !!");
        }
        Dinero = Dinero - compensacion;

        // Vemos si tenemos que echar a alguien
        if (MINCAPITAL > Dinero) {
            int rand;
            // Echamos a un numero aleatorio de trabajadores
            rand = rd.nextInt(4) + 1;
            if (Trabajadores < rand) {
                rand = Trabajadores;
                Estado = TipoEstadoEmpresa.Bancarrota;
                System.out.println("!! La empresa esta en Bancarrota !!");
            }
            System.out.println("<!! La empresa ha echado a "+rand+" trabajadores.");
            Trabajadores = Trabajadores - rand;
        }
        return compensacion;
    }

    public synchronized int PedirFactura() {
        return (rd.nextInt(4) + 1) * 5;
    }

    public synchronized void DevolverTrabajadores(int tbj) {
        Trabajadores = Trabajadores + tbj;
    }
}

class Cliente extends Thread{
      private int id;
      private int tbj;
      private int compensacion;
      private int importe;
      private Director director;
      Random rd = new Random();

      public Cliente(int id, Director director){
        this.id=id;
        this.director=director;
      }
      
      
    @Override
    public void run(){
        try {
            int rand;

            sleep((rd.nextInt(4) + 1) * 5000);

            System.out.println("--> El cliente " + id + " ha solicitado un servicio.");
            tbj = director.SolicitarServicio();
            if (tbj == 0) {
                System.out.println("<-- El cliente " + id + " se va porque la empresa esta en Bancarrota o no tiene trabajadores libre en este momento.");
            } else {
                try {
                    System.out.println("++ El cliente " + id + " ha recibido " + tbj + " trabajadores. Empiezan a trabajar!!! ");
                    sleep((rd.nextInt(4) + 1) * 10000);
                    System.out.println("-- Se ha finalizado el servicio al cliente " + id);
                    // Devolvemos los trabajadores que han realizado el servicio
                    director.DevolverTrabajadores(tbj);

                    rand = rd.nextInt(1);
                    if (rand == 0) {
                        // No denunciamos
                        System.out.println("??> El cliente " + id + " pide la factura. ");
                        importe = director.PedirFactura();
                        director.Pagar(importe);
                        System.out.println("++$$ El cliente " + id + " ha pagado " + importe + " Euros y se ha ido sadisfecho. ");
                    } else if (rand == 1) {
                        // Denunciamos
                        compensacion = director.Demandar();
                        System.out.println("--$$ El cliente " + id + " ha demandado a la emplesa y ha cobrado una compensacion de " + compensacion + " Euros. ");
                    }
                } catch (InterruptedException ex) {
                    Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } catch (InterruptedException ex) {
            Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

